package com.zhkj.crawl.rank;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.zhkj.crawl.config.*;
import com.zhkj.crawl.service.impl.ChromeService;
import com.zhkj.crawl.utils.Ocr;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.concurrent.TimeUnit;

import static com.zhkj.crawl.config.FetchRankException.Type.NONE_INFO;

@Slf4j
public class AmzService extends BaseService{

    public static void main(String[] args) throws Exception {
        // https://www.amazon.it/dp/B09FK227CS?language=en_US&th=1
        OkHttpPool.setTypeForward();
        Config.proxySwitch = false;
        ProductDetail detail = start("B07K6D3Y3R", "UK");
        Element element = detail.getElement();
        if(StringUtils.isBlank(detail.getRank()) && StringUtils.isNotBlank(detail.getRating())){
            int i = 0;
        }
        detail.setElement(null);
        log.info("{} 的详情：{}", detail.getItemId(), JSON.toJSONString(detail));
    }

    private static void analysisResult(ProductDetail detail) {
        if(detail.getElement() == null){ return; }
        Element body = detail.getElement();

        // 星级
        Elements star = body.select("#averageCustomerReviews i.a-icon-star");
        if(star != null && star.size() > 0){
            detail.setStar(star.first().text());
        }

        // 评论数
        Elements reviews = body.select("#acrCustomerReviewText");
        if(reviews != null && reviews.size() > 0){
            detail.setRating(reviews.first().text());
        }

        // 排名
        findRank(body, detail);
    }

    public static ProductDetail start(String asin, String countryCode) {
        ProductDetail detail = new ProductDetail(asin);
        AmzSiteParamEnum siteParamEnum = AmzSiteParamEnum.getByCountryCode(countryCode);
        detail.setSiteParam(siteParamEnum);

        long start = System.currentTimeMillis();
        int deep = 0;
        getContent(detail, deep);
        // 没用代理则单条限制时间
        long distance = Config.LIMIT_MIL_SEC - (System.currentTimeMillis() - start);
        if(!Config.proxySwitch && distance > 0){
            try { TimeUnit.MILLISECONDS.sleep(distance); }catch (Exception ignore){}
        }

        return detail;
    }
    private static void findRank(Element body, ProductDetail detail){
        String keywordRank = detail.getSiteParam().keywordRank;
        String keywordRankCn = "亚马逊热销商品排行榜";

        Elements spans = body.select("#detailBulletsWrapper_feature_div span.a-text-bold");
        for (Element element : spans) {
            String text = element.text();
            if(StringUtils.isBlank(text)){
                continue;
            }
            if(keywordRank.contains(StringPool.SEMICOLON)){
                for (String k : keywordRank.split(StringPool.SEMICOLON)) {
                    if(text.contains(k)){
                        String rank = element.parent().text().replace(k, StringPool.EMPTY);
                        rank = rank.replace(StringPool.COLON, StringPool.EMPTY).trim();
                        detail.setRank(rank);
                        return;
                    }
                }
            }else {
                if(text.contains(keywordRank)){
                    String rank = element.parent().text().replace(keywordRank, StringPool.EMPTY);
                    rank = rank.replace(StringPool.COLON, StringPool.EMPTY).trim();
                    detail.setRank(rank);
                    return;
                }
            }
            if(text.contains(keywordRankCn)){
                String rank = element.parent().text().replace(keywordRankCn, StringPool.EMPTY);
                rank = rank.replace(StringPool.COLON, StringPool.EMPTY).trim();
                detail.setRank(rank);
                return;
            }
        }

        Elements table = body.select("th.prodDetSectionEntry");
        for (Element element : table) {
            String text = element.text();
            if(StringUtils.isBlank(text)){
                continue;
            }

            if(keywordRank.contains(StringPool.SEMICOLON)){
                for (String k : keywordRank.split(StringPool.SEMICOLON)) {
                    if(text.contains(k)){
                        detail.setRank(element.siblingElements().get(0).text());
                        return;
                    }
                }
            }else {
                if(text.contains(keywordRank)){
                    detail.setRank(element.siblingElements().get(0).text());
                    return;
                }
            }

            if(text.contains(keywordRankCn)){
                detail.setRank(element.siblingElements().get(0).text());
                return;
            }
        }
    }


    private static void getContent(ProductDetail detail, Integer deep){
        ++deep;
        String url = String.format("%sdp/%s?language=en_US", detail.getSiteParam().siteUrl, detail.getItemId());

        detail.setUrl(url);
//        Element document = jsoupGet(url, deep).body();
        Document document = seleniumGet(url, deep);
        document = captchaHandler(document);

        document = titleHandler(document, url);

        detail.setElement(document);

        analysisResult(detail);

        // 有rating或star 但是没有rank:重置下次再跑
        if(shouldRetry(detail)){
            if(deep <= 3){
//                sleep(1);
//                log.info("{}（{}） 未取到rank 重试{}", detail.getItemId(), url, deep);
//                getContent(detail, deep);
//                return;
//            }else {
                log.info("{}（{}） 尝试{}次未取到 清除结果下次重试", detail.getItemId(), url, deep);
                detail.setStar(StringPool.EMPTY);
                detail.setRating(StringPool.EMPTY);
                return;
            }
        }

        // 3个都没有 但是内容已经出来了(title)
        Elements productTitle = document.select("#productTitle");
        if(StringUtils.isAllBlank(detail.getRank(), detail.getStar(), detail.getRating())
            && CollUtil.isNotEmpty(productTitle)){
            //log.info("{} 是三无listing {}", detail.getItemId(), detail.getUrl());
            throw new FetchRankException(NONE_INFO.msg, NONE_INFO, url);
        }

    }

    private static Document titleHandler(Document document, String url) {
        // Warning: Adult Content
        Elements titles = document.select("title");
        if(titles == null || titles.size() == 0){
            return document;
        }
        Element title = titles.get(0);
        String titleStr = title.text();
        if(StringUtils.isNotBlank(titleStr)){
            int adultDeep = 0;
            while (titleStr.contains("Adult Content") && adultDeep < 5){
                ++adultDeep;
                String xpath = "//*[@id=\"black-curtain-yes-button\"]/span/a";
                Document newDoc = ChromeService.jumpByXpath(xpath);

                titles = newDoc.select("title");
                if(titles == null || titles.size() == 0){
                    return document;
                }
                title = titles.get(0);
                titleStr = title.text();
                boolean pass = !titleStr.contains("Adult Content");
                log.info("Age Verification {}", pass);
                if(pass){
                    return newDoc;
                }
            }

            if(titleStr.contains("Page Not Found") || titleStr.contains("找不到页面")){
                throw new FetchRankException(titleStr, FetchRankException.Type.INVALID, url);
            }

            Elements links = document.select("a");
            if(CollUtil.isNotEmpty(links) && links.get(0).attr("href").equals("/ref=cs_404_logo")){
                throw new FetchRankException(titleStr, FetchRankException.Type.INVALID, url);
            }
        }
        return document;
    }

    // 处理验证码
    private static Document captchaHandler(Document document) {
        int captchaDeep = 0;
        // 处理验证码
        String captchaIptId = "captchacharacters";
        String submitPath = "/html/body/div/div[1]/div[3]/div/div/form/div[2]/div/span/span/button";
        Element captchaIpt = document.getElementById(captchaIptId);
        while ((captchaIpt != null) && captchaDeep < 5){
            ++captchaDeep;
            String captchaUrl = captchaIpt.parent().previousElementSibling().select("img").get(0).attr("src");
            String result = Ocr.recognizePy(captchaUrl);
            ChromeService.fillIptById(captchaIptId, result);
            document = ChromeService.jumpByXpath(submitPath);
            captchaIpt = document.getElementById(captchaIptId);
            boolean recognizeResult = (captchaIpt == null);
            log.info("第{}次识别验证码：{}-{}（{}）", captchaDeep, result, recognizeResult, captchaUrl);
        }
        return document;
    }

    private static boolean shouldRetry(ProductDetail detail) {
        Element body = detail.getElement();
        if(StringUtils.isBlank(detail.getRank())){
            if(StringUtils.isNotBlank(detail.getRating())
                    && body.getElementsContainingOwnText(detail.getRating()).size() == 1){
                return true;
            }
            if(StringUtils.isNotBlank(detail.getStar())
                    && body.getElementsContainingOwnText(detail.getStar()).size() <= 2){
                return true;
            }
        }
        // add extra strategy...

        return false;
    }


}
